package com.hm.oltu.api;

import java.net.URI;
import java.text.MessageFormat;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.as.response.OAuthASResponse.OAuthAuthorizationResponseBuilder;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.error.OAuthError;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.types.ResponseType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.hm.common.util.CommonUtil;
import com.hm.common.util.StringUtil;
import com.hm.oltu.def.OauthDef;
import com.hm.oltu.model.User;
import com.hm.oltu.service.OAuthService;
import com.hm.oltu.service.UserService;

import lombok.extern.slf4j.Slf4j;

/**
 * @author shishun.wang
 * @date 2016年12月6日 上午10:50:06
 * @version 1.0
 * @describe 授权
 */
@Slf4j
@RestController
public class AuthorizeController {

	@Autowired
	private OAuthService oAuthService;

	@Autowired
	private UserService userService;

	@RequestMapping(value = "/authorize", method = RequestMethod.POST)
	public Object authorize(HttpServletRequest request) {
		try {
			String username = request.getParameter("username");
			String password = request.getParameter("password");
			
			if (CommonUtil.isAnyEmpty(username, password)) {
				return error(HttpServletResponse.SC_BAD_REQUEST, OauthDef.PARAM_ERROR,
						OauthDef.USERNAME_OR_PASSWORD_EMPTY);
			}
			OAuthAuthzRequest authzRequest = new OAuthAuthzRequest(request);
			if (CommonUtil.isEmpty(authzRequest.getClientId())
					|| !oAuthService.checkClientId(authzRequest.getClientId())) {
				return error(HttpServletResponse.SC_BAD_REQUEST, OAuthError.TokenResponse.INVALID_CLIENT,
						OauthDef.INVALID_CLIENT_ID);
			}

			// responseType目前仅支持CODE，另外还有TOKEN
			String responseType = authzRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);
			if (CommonUtil.isEmpty(responseType) || !responseType.equals(ResponseType.CODE.toString())) {
				return error(HttpServletResponse.SC_BAD_REQUEST, OauthDef.PARAM_ERROR, OauthDef.RESPONSE_TYPE_ERROR);
			}
			// 得到到客户端重定向地址
			String redirectURI = authzRequest.getParam(OAuth.OAUTH_REDIRECT_URI);
			if (StringUtil.isBlank(redirectURI)) {
				return error(HttpStatus.NOT_FOUND.value(), OauthDef.RESPONSE_ERROR, OauthDef.CALLBACK_URL_NOT_FOUND);
			}

			{// 检查用户名密码是否匹配
				User user = userService.findByUsername(username);
				if (CommonUtil.isEmpty(user)) {
					return error(HttpServletResponse.SC_BAD_REQUEST, OauthDef.PARAM_ERROR,
							MessageFormat.format(OauthDef.NOTFOUND_USERNAME, username));
				}
				if (!userService.checkUser(username, password, user.getSalt(), user.getPassword())) {
					return error(HttpServletResponse.SC_BAD_REQUEST, OauthDef.PARAM_ERROR,
							MessageFormat.format(OauthDef.PASSWORD_ERROR, username));
				}
			}

			OAuthAuthorizationResponseBuilder authorizationResponse = OAuthASResponse.authorizationResponse(request,
					HttpServletResponse.SC_FOUND);
			OAuthIssuerImpl oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
			String authorizationCode = oauthIssuerImpl.authorizationCode();
			authorizationResponse.setCode(authorizationCode);
			oAuthService.addAuthCode(authorizationCode, username);// 加入redis缓存中

			OAuthResponse response = authorizationResponse.location(redirectURI).buildQueryMessage();
			HttpHeaders headers = new HttpHeaders();
			headers.setLocation(new URI(response.getLocationUri()));

			Thread.sleep(500);
			
			return new ResponseEntity<Object>(headers, HttpStatus.valueOf(response.getResponseStatus()));
		} catch (Exception e) {
			log.error("authorize other error $s ", e.getMessage());
			e.printStackTrace();
			return error(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), OauthDef.OTHER_ERROR);
		}
	}

	private ResponseEntity<String> error(int responseStatu, String error, String desc) {
		try {
			log.error("authorize error responseStatu=[$s],error=[$s] ,desc=[$s]", responseStatu, error, desc);
			OAuthResponse response = OAuthASResponse.errorResponse(responseStatu).setError(error)
					.setErrorDescription(desc).buildJSONMessage();
			return new ResponseEntity<String>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));
		} catch (OAuthSystemException e) {
			log.error("authorize other error $s ", e.getMessage());
			return error(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage(), OauthDef.OTHER_ERROR);
		}
	}
}
